use std::fs;
use std::process::exit;
use std::str::FromStr;

use crate::{Chunk, ChunkType, Png, Result};
use crate::args::Commands;

impl Commands {
    /// 执行当前的子命令
    pub fn execute(&self) -> Result<()> {
        match self {
            Commands::Encode {
                input,
                chunk_type,
                message,
                output,
            } => {
                // —— Encode 逻辑 ——

                // 1. 先读入整个文件字节
                let raw_bytes = fs::read(&input).unwrap_or_else(|e| {
                    eprintln!("无法读取文件 {:?}: {}", input, e);
                    exit(1);
                });

                // 2. 解析成 Png
                let mut png = match Png::try_from(raw_bytes.as_slice()) {
                    Ok(p) => p,
                    Err(e) => {
                        eprintln!("解析 PNG 失败: {}", e);
                        exit(1);
                    }
                };

                // 3. chunk_type 字符串 -> 库里的 ChunkType
                let ct = match ChunkType::from_str(chunk_type) {
                    Ok(ct) => ct,
                    Err(e) => {
                        eprintln!("无效的 chunk type '{}': {}", chunk_type, e);
                        exit(1);
                    }
                };

                // 4. 把消息转成 Vec<u8>，然后构造 Chunk
                let data_bytes: Vec<u8> = message.clone().into_bytes();
                let new_chunk = Chunk::new(ct, data_bytes);

                // 5. 插入 chunk
                png.append_chunk(new_chunk);

                // 6. 把修改后的 png 序列化为字节
                let out_bytes = png.as_bytes();

                // 7. 确定输出路径：如果用户给了 --output，就用它；否则覆盖原文件
                let target = output.as_ref().unwrap_or(input);

                // 8. 写回文件
                if let Err(e) = fs::write(&target, &out_bytes) {
                    eprintln!("写入 PNG 失败 {:?}: {}", target, e);
                    exit(1);
                }

                println!(
                    "成功将消息写入 '{}'，输出文件：'{:?}'",
                    input.display(),
                    target
                );
                Ok(())
            }

            Commands::Decode {
                input,
                chunk_type,
            } => {
                // —— Decode 逻辑 ——

                let raw_bytes = fs::read(&input).unwrap_or_else(|e| {
                    eprintln!("无法读取文件 {:?}: {}", input, e);
                    exit(1);
                });
                let png = match Png::try_from(raw_bytes.as_slice()) {
                    Ok(p) => p,
                    Err(e) => {
                        eprintln!("解析 PNG 失败: {}", e);
                        exit(1);
                    }
                };

                // 验证 chunk_type
                let _ct = match ChunkType::from_str(chunk_type) {
                    Ok(ct) => ct,
                    Err(e) => {
                        eprintln!("无效的 chunk type '{}': {}", chunk_type, e);
                        exit(1);
                    }
                };

                // 查找第一个符合类型的 chunk
                if let Some(found) = png.chunk_by_type(chunk_type) {
                    // 把 data 部分当 UTF-8 文本打印出来
                    match found.data_as_string() {
                        Ok(s) => {
                            println!("Found message in chunk '{}': {}", chunk_type, s);
                            Ok(())
                        }
                        Err(e) => {
                            eprintln!(
                                "chunk '{}' 的 data 不是合法 UTF-8: {}",
                                chunk_type, e
                            );
                            exit(1);
                        }
                    }
                } else {
                    eprintln!("PNG 中没有类型为 '{}' 的 chunk。", chunk_type);
                    exit(1);
                }
            }

            Commands::Remove {
                input,
                chunk_type,
            } => {
                // —— Remove 逻辑 ——

                let raw_bytes = fs::read(&input).unwrap_or_else(|e| {
                    eprintln!("无法读取文件 {:?}: {}", input, e);
                    exit(1);
                });
                let mut png = match Png::try_from(raw_bytes.as_slice()) {
                    Ok(p) => p,
                    Err(e) => {
                        eprintln!("解析 PNG 失败: {}", e);
                        exit(1);
                    }
                };

                // 验证 chunk_type
                let _ct = match ChunkType::from_str(chunk_type) {
                    Ok(ct) => ct,
                    Err(e) => {
                        eprintln!("无效的 chunk type '{}': {}", chunk_type, e);
                        exit(1);
                    }
                };

                // 调用 remove_first_chunk
                match png.remove_first_chunk(chunk_type) {
                    Ok(_removed_chunk) => {
                        // 成功删除后，把新的 png 写回原文件
                        let out_bytes = png.as_bytes();
                        if let Err(e) = fs::write(&input, &out_bytes) {
                            eprintln!("写入 PNG 失败 {:?}: {}", input, e);
                            exit(1);
                        }
                        println!("已删除类型 '{}' 的第一个 chunk，已写回 {}。", chunk_type, input.display());
                        Ok(())
                    }
                    Err(_) => {
                        eprintln!("PNG 中没有类型为 '{}' 的 chunk，无法删除。", chunk_type);
                        exit(1);
                    }
                }
            }

            Commands::Print { input } => {
                // —— Print 逻辑 ——

                let raw_bytes = fs::read(&input).unwrap_or_else(|e| {
                    eprintln!("无法读取文件 {:?}: {}", input, e);
                    exit(1);
                });
                let png = match Png::try_from(raw_bytes.as_slice()) {
                    Ok(p) => p,
                    Err(e) => {
                        eprintln!("解析 PNG 失败: {}", e);
                        exit(1);
                    }
                };

                println!("PNG 文件 '{}' 中的 chunk 列表：", input.display());
                for chunk in png.chunks().iter() {
                    println!(
                        "- 类型: {:4}, 长度: {:>5}, CRC: 0x{:08X}",
                        chunk.chunk_type().to_string(),
                        chunk.length(),
                        chunk.crc()
                    );
                }
                Ok(())
            }
        }
    }
}

